﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.AccessControl;

using Microsoft.VisualBasic.FileIO;

namespace ManageATrois
{

    public delegate void ProfileCallback();

    public partial class MainForm : Form
    {
        private const int MAX_BTNS = 200;

        public Button[] sourceCopyBtns = new Button[MAX_BTNS];
        public Button[] destCopyBtns = new Button[MAX_BTNS];
        public Button[] deleteSourceBtns = new Button[MAX_BTNS];
        public Button[] deleteDestBtns = new Button[MAX_BTNS];

        public Button[] moveSourceBtns = new Button[MAX_BTNS];
        public Button[] moveDestBtns = new Button[MAX_BTNS];

        private int btnCount = -1;

        private ProfileDialog pd;
        private FolderReadProgress frp;
        private FolderMoveProgress fmp;

        public MainForm()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Timer updateTimer = new Timer();
            updateTimer.Interval = 1000;
            updateTimer.Tick += new EventHandler(UpdateTick);
            updateTimer.Start();

            fmp = new FolderMoveProgress();
            frp = new FolderReadProgress();

            pd = new ProfileDialog();
            pd.Init();
            try
            {
                PopuplateProfile(pd.GetSelectedProfile());
            }
            catch (System.Exception ex)
            {
                CurProfileLbl.Text = "NULL";
            }

            pd.DialogClosed += new ProfileCallback(ProfileDialogCallback);
        }

        private void ProfileDialogCallback()
        {
            PopuplateProfile(pd.GetSelectedProfile());
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            pd.Show(this.Owner);
        }

        private void UpdateTick(object sender, EventArgs e)
        {
            //long sourceSize = 0;
            //long sourceDriveSize = 0;
            //long destSize = 0;
            //long destDriveSize = 0;
            //try
            //{
            //    DirectoryInfo di = new DirectoryInfo(pd.GetSelectedProfile().SourceFolder);
            //    sourceDriveSize = DirSize(di);
            //} catch (System.Exception ex) { }

            //try
            //{
            //    int driveIndex = pd.GetSelectedProfile().SourceFolder.IndexOf("\\", 0) + 1;
            //    string driveFolder = pd.GetSelectedProfile().SourceFolder.Substring(0 , driveIndex);
            //    DirectoryInfo di = new DirectoryInfo(driveFolder);
            //    sourceSize = DirSize(di);
            //}
            //catch (System.Exception ex) { }

            //try
            //{
            //    DirectoryInfo di = new DirectoryInfo(pd.GetSelectedProfile().DestFolder);
            //    destSize = DirSize(di);
            //}
            //catch (System.Exception ex) { }

            //try
            //{
            //    int driveIndex = pd.GetSelectedProfile().DestFolder.IndexOf("\\", 0) + 1;
            //    string driveFolder = pd.GetSelectedProfile().DestFolder.Substring(0, driveIndex);
            //    DirectoryInfo di = new DirectoryInfo(driveFolder);
            //    destDriveSize = DirSize(di);
            //}
            //catch (System.Exception ex) { }

            //toolStripStatusLabel1.Text = "Source Size: " + FormatSize(sourceSize) + "(Drive:" + FormatSize(sourceDriveSize) + ") .. DestSize: " +
            //                             FormatSize(destSize) + "(Drive:" + FormatSize(destDriveSize) + ") ";
        }

        private void PopuplateProfile(Profile prof)
        {
            if (prof == null)
                return;

            int scrollVal = btnPanel.VerticalScroll.Value;

            CurProfileLbl.Text = prof.Name;

            for (int i = 0; i <= btnCount; i++)
            {
                btnPanel.Controls.Remove(sourceCopyBtns[i]);
                sourceCopyBtns[i] = null;

                btnPanel.Controls.Remove(destCopyBtns[i]);
                destCopyBtns[i] = null;

                btnPanel.Controls.Remove(deleteSourceBtns[i]);
                deleteSourceBtns[i] = null;

                btnPanel.Controls.Remove(deleteDestBtns[i]);
                deleteDestBtns[i] = null;

                btnPanel.Controls.Remove(moveSourceBtns[i]);
                moveSourceBtns[i] = null;

                btnPanel.Controls.Remove(moveDestBtns[i]);
                moveDestBtns[i] = null;
            }

            btnCount = -1;

            frp.Show(this.Owner);
            frp.Update();

            dataGridView1.ColumnHeadersVisible = false;
            dataGridView1.ColumnCount = 2;
            dataGridView1.RowHeadersWidth = 250;
            string[] filePaths = Directory.GetDirectories(prof.SourceFolder);
            int numFPs = filePaths.Length;
            dataGridView1.RowCount = numFPs;

            int addHeight = 0;
            for (int i = 0; i < numFPs; i++)
            {
                string folderName = filePaths[i].Substring(filePaths[i].LastIndexOf('\\') + 1);

                frp.SetSourceFolderInfo(("Source Folder: " + folderName), ((i * 100) / numFPs));
                frp.Update();

                dataGridView1.Rows[i].HeaderCell.Value = folderName;
                DirectoryInfo di = new DirectoryInfo(filePaths[i]);

                long sourceDirSize = DirSize(di);
                long destDirSize = 0;
                try
                {
                    frp.SetDestFolderInfo(("Dest Folder: " + folderName), ((i * 100) / numFPs));
                    frp.Update();

                    di = new DirectoryInfo(prof.DestFolder + "\\" + folderName);
                    destDirSize = DirSize(di);
                }
                catch (System.Exception ex)
                { }

                dataGridView1.Rows[i].Cells[0].Value = FormatSize(sourceDirSize);
                dataGridView1.Rows[i].Cells[1].Value = FormatSize(destDirSize);

                //dataGridView1.Rows[i].HeaderCell.Size.Height / 2 

                //int yPos = 2 + (i * 20);

                int yPos = addHeight + (dataGridView1.Rows[i].HeaderCell.Size.Height / 2) - 8;
                addHeight += dataGridView1.Rows[i].HeaderCell.Size.Height;

                moveSourceBtns[i] = new Button();
                moveSourceBtns[i].Text = "<---";
                moveSourceBtns[i].Size = new Size(40, 18);
                moveSourceBtns[i].Location = new Point(450, yPos);
                btnPanel.Controls.Add(moveSourceBtns[i]);
                moveSourceBtns[i].Enabled = false;
                moveSourceBtns[i].Click += new EventHandler(SourceMove_Click);

                moveDestBtns[i] = new Button();
                moveDestBtns[i].Text = "--->";
                moveDestBtns[i].Size = new Size(40, 18);
                moveDestBtns[i].Location = new Point(490, yPos);
                btnPanel.Controls.Add(moveDestBtns[i]);
                moveDestBtns[i].Enabled = false;
                moveDestBtns[i].Click += new EventHandler(DestMove_Click);

                sourceCopyBtns[i] = new Button();
                sourceCopyBtns[i].Text = "<-";
                sourceCopyBtns[i].Size = new Size(30, 18);
                sourceCopyBtns[i].Location = new Point(540, yPos);
                btnPanel.Controls.Add(sourceCopyBtns[i]);
                sourceCopyBtns[i].Enabled = false;
                sourceCopyBtns[i].Click += new EventHandler(SourceCopy_Click);

                destCopyBtns[i] = new Button();
                destCopyBtns[i].Text = "->";
                destCopyBtns[i].Size = new Size(30, 18);
                destCopyBtns[i].Location = new Point(575, yPos);
                btnPanel.Controls.Add(destCopyBtns[i]);
                destCopyBtns[i].Enabled = false;
                destCopyBtns[i].Click += new EventHandler(DestCopy_Click);

                deleteSourceBtns[i] = new Button();
                deleteSourceBtns[i].Text = "S";
                deleteSourceBtns[i].Size = new Size(20, 18);
                deleteSourceBtns[i].Location = new Point(615, yPos);
                btnPanel.Controls.Add(deleteSourceBtns[i]);
                deleteSourceBtns[i].Click += new EventHandler(SourceDel_Click);

                deleteDestBtns[i] = new Button();
                deleteDestBtns[i].Text = "D";
                deleteDestBtns[i].Size = new Size(20, 18);
                deleteDestBtns[i].Location = new Point(640, yPos);
                btnPanel.Controls.Add(deleteDestBtns[i]);
                deleteDestBtns[i].Click += new EventHandler(DestDel_Click);

                btnCount = i;

                if ((sourceDirSize == 0) && (destDirSize > 0))
                {
                    sourceCopyBtns[i].Enabled = true;
                    moveSourceBtns[i].Enabled = true;
                }
                if ((destDirSize == 0) && (sourceDirSize > 0))
                {
                    destCopyBtns[i].Enabled = true;
                    moveDestBtns[i].Enabled = true;
                }
            }

            frp.Hide();

            btnPanel.VerticalScroll.Value = scrollVal;
            btnPanel.Invalidate(true);
            btnPanel.Update();
        }

        public static string FormatSize(long bytes)
        {
            float mbs = (bytes / 1024.0f) / 1024.0f;
            string returnString;

            returnString = mbs + " MB";
            return returnString;
        }

        public static long DirSize(DirectoryInfo d)
        {
            long Size = 0;
            // Add file sizes.
            FileInfo[] fis = d.GetFiles();
            foreach (FileInfo fi in fis)
            {
                Size += fi.Length;
            }
            // Add subdirectory sizes.
            DirectoryInfo[] dis = d.GetDirectories();
            foreach (DirectoryInfo di in dis)
            {
                Size += DirSize(di);
            }
            return (Size);
        }

        private static void CopyFullDirectory(string sourceFolder, string destFolder, bool accessControl)
        {
            if (!System.IO.Directory.Exists(destFolder))
                System.IO.Directory.CreateDirectory(destFolder);

            if (accessControl)
            {
                System.Security.AccessControl.DirectorySecurity sec = System.IO.Directory.GetAccessControl(destFolder);
                FileSystemAccessRule accRule = new FileSystemAccessRule(Environment.UserDomainName + "\\" + Environment.UserName, FileSystemRights.FullControl, AccessControlType.Allow);
                sec.AddAccessRule(accRule);
            }

            try
            {
                FileSystem.CopyDirectory(sourceFolder, destFolder, UIOption.AllDialogs);
            }
            catch (System.Exception ex)
            {
            }
        }

        private static void EmptyDirectory(string delFolder, bool accessControl, bool deleteSelf)
        {
            try
            {
                if (accessControl)
                {
                    System.Security.AccessControl.DirectorySecurity sec = System.IO.Directory.GetAccessControl(delFolder);
                    FileSystemAccessRule accRule = new FileSystemAccessRule(Environment.UserDomainName + "\\" + Environment.UserName, FileSystemRights.FullControl, AccessControlType.Allow);
                    sec.AddAccessRule(accRule);
                }

                string[] files = System.IO.Directory.GetFiles(delFolder);
                // Copy the files and overwrite destination files if they already exist.
                foreach (string s in files)
                    System.IO.File.Delete(s);

                string[] dirs = System.IO.Directory.GetDirectories(delFolder);
                foreach (string s in dirs)
                {
                    string dir = s;
                    string recurseDest = delFolder + dir.Substring(dir.LastIndexOf("\\"));
                    EmptyDirectory(recurseDest, false, true);
                }
            }
            catch (System.Exception ex)
            {	
            }

            if (deleteSelf)
                System.IO.Directory.Delete(delFolder);
        }

        public void UpdateGameIndex(int i, string sourceFolder, string destFolder )
        {
            DirectoryInfo di = new DirectoryInfo(sourceFolder);
            long sourceDirSize = DirSize(di);
            long destDirSize = 0;
            try
            {
                di = new DirectoryInfo(destFolder);
                destDirSize = DirSize(di);
            }
            catch (System.Exception ex)
            { }

            dataGridView1.Rows[i].Cells[0].Value = FormatSize(sourceDirSize);
            dataGridView1.Rows[i].Cells[1].Value = FormatSize(destDirSize);

            sourceCopyBtns[i].Enabled = false;
            destCopyBtns[i].Enabled = false;
            moveSourceBtns[i].Enabled = false;
            moveDestBtns[i].Enabled = false;
            if ((sourceDirSize == 0) && (destDirSize > 0))
            {
                sourceCopyBtns[i].Enabled = true;
                moveSourceBtns[i].Enabled = true;
            }
            if ((destDirSize == 0) && (sourceDirSize > 0))
            {
                destCopyBtns[i].Enabled = true;
                moveDestBtns[i].Enabled = true;
            }
        }

        public void CopyGameIndex(int i, bool reverse = false)
        {

            string sourceFolder = pd.GetSelectedProfile().SourceFolder + "\\" + dataGridView1.Rows[i].HeaderCell.Value;
            string destFolder = pd.GetSelectedProfile().DestFolder + "\\" + dataGridView1.Rows[i].HeaderCell.Value;

            if (!reverse)
                CopyFullDirectory(sourceFolder, destFolder, true);
            else
                CopyFullDirectory(destFolder, sourceFolder, true);

            UpdateGameIndex(i, sourceFolder, destFolder );
        }

        public void DestCopy_Click(object o, EventArgs ea)
        {
            int destIndex = indexOf(o, destCopyBtns);
            if (destIndex < 0)
                return;

            destCopyBtns[destIndex].Enabled = false;

            CopyGameIndex(destIndex);
        }

        public void SourceCopy_Click(object o, EventArgs ea)
        {
            int sourceIndex = indexOf(o, sourceCopyBtns);
            if (sourceIndex < 0)
                return;

            sourceCopyBtns[sourceIndex].Enabled = false;

            CopyGameIndex(sourceIndex, true);
        }

        public void SourceDel_Click(object o, EventArgs ea)
        {
            int destIndex = indexOf(o, deleteSourceBtns);
            if (destIndex < 0)
                return;

            string sourceFolder = pd.GetSelectedProfile().SourceFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;
            string destFolder = pd.GetSelectedProfile().DestFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;
            EmptyDirectory(sourceFolder, true, false);

            UpdateGameIndex(destIndex, sourceFolder, destFolder);
        }

        public void DestDel_Click(object o, EventArgs ea)
        {
            int destIndex = indexOf(o, deleteDestBtns);
            if (destIndex < 0)
                return;

            string sourceFolder = pd.GetSelectedProfile().SourceFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;
            string destFolder = pd.GetSelectedProfile().DestFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;
            EmptyDirectory(destFolder, true, false);

            UpdateGameIndex(destIndex, sourceFolder, destFolder);
        }

        public void SourceMove_Click(object o, EventArgs ea)
        {
            int destIndex = indexOf(o, moveSourceBtns);
            if (destIndex < 0)
                return;

            string sourceFolder = pd.GetSelectedProfile().SourceFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;
            string destFolder = pd.GetSelectedProfile().DestFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;

            MoveFolder(destIndex, destFolder, sourceFolder, true);
            UpdateGameIndex(destIndex, sourceFolder, destFolder);
        }

        public void DestMove_Click(object o, EventArgs ea)
        {
            int destIndex = indexOf(o, moveDestBtns);
            if (destIndex < 0)
                return;

            string sourceFolder = pd.GetSelectedProfile().SourceFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;
            string destFolder = pd.GetSelectedProfile().DestFolder + "\\" + dataGridView1.Rows[destIndex].HeaderCell.Value;

            MoveFolder(destIndex, sourceFolder, destFolder);
            UpdateGameIndex(destIndex, sourceFolder, destFolder);
        }

        public void MoveFolder(int i, string sourceFolder, string destFolder, bool reverse = false)
        {
            fmp.Show(this.Owner);
            fmp.UpdateFolders(sourceFolder, destFolder);
            fmp.UpdateStep(1);

            EmptyDirectory(destFolder, true, false);

            fmp.UpdateStep(2);

            CopyGameIndex(i,reverse);

            fmp.UpdateStep(3);

            EmptyDirectory(sourceFolder, true, false);

            fmp.Hide();
        }

        public int indexOf(object o, object[] objArray)
        {
            for (int i = 0; i <= objArray.Length; i++)
            {
                if (o == objArray[i])
                    return i;
            }

            return -1;
        }
    }
}
